////////////////////////////////////////////////////////////////////////////////

#include "server_session.h"

////////////////////////////////////////////////////////////////////////////////

#include "mutex.h"
#include "timer.h"

////////////////////////////////////////////////////////////////////////////////


ServerSession::ServerSession( SOCKET _sendSocket,
                              SOCKET _recvSocket,
                              ClientPackets& _recvQueue,
                              ServerPackets& _sendQueue,
                              Mutex& _sendQueueMutex,
                              Mutex& _recvQueueMutex )
: m_SendSocket(_sendSocket),
  m_RecvSocket(_recvSocket),
  m_RecvQueue(_recvQueue),
  m_SendQueue(_sendQueue),
  m_RecvQueueMutex(_recvQueueMutex),
  m_SendQueueMutex(_sendQueueMutex),
  m_SendThread(NULL),
  m_RecvThread(NULL)
{
}


////////////////////////////////////////////////////////////////////////////////


ServerSession::~ServerSession()
{
    // Stop sending
    if (m_SendThread)
    {
        delete m_SendThread;
        shutdown(m_SendSocket, SD_SEND);
        closesocket(m_SendSocket);
    }

    // Stop receiving
    if (m_RecvThread)
    {
        delete m_RecvThread;
        shutdown(m_RecvSocket, SD_RECEIVE);
        closesocket(m_RecvSocket);
    }
}


////////////////////////////////////////////////////////////////////////////////


void ServerSession::Send()
{
    bool continueSending = true;
    while (continueSending)
    {
        // Lock collection
        m_SendQueueMutex.Lock();

        // Send all
        while( !m_SendQueue.empty() && continueSending )
        {
            ServerPacket& packet = m_SendQueue.back();
            int sendResult = send( m_SendSocket, &packet.ToStr()[0], packet.Size() + sizeof(short), 0 );
            continueSending = (sendResult != SOCKET_ERROR);
            m_SendQueue.pop();
        }

        // Unlock
        m_SendQueueMutex.Unlock();

        // Be kind to CPU
        Timer::Delay(1);
    }
}


////////////////////////////////////////////////////////////////////////////////


void ServerSession::Receive()
{
    bool continueReceiving = true;
    while (continueReceiving)
    {
        ClientPacket packet;
        const int packetSize = packet.Size();
        std::vector<char> recvbuf(packetSize);

        // Receive 1 packet
        int bytesReveived = recv(m_RecvSocket, &recvbuf[0], packetSize, 0);
        continueReceiving = (bytesReveived == packetSize);

        if (continueReceiving)
        {
            packet.FromStr(&recvbuf[0]);

            // Lock recv collection
            m_RecvQueueMutex.Lock();
            m_RecvQueue.push(packet);

            // Unlock
            m_RecvQueueMutex.Unlock();

            // Be kind to CPU
            Timer::Delay(1);
        }
    }
}


////////////////////////////////////////////////////////////////////////////////


void ServerSession::Start()
{
    if (!m_SendThread)
    {
        // Start thread for sending
        m_SendThread = new Thread(&ServerSession::Send, this);
    }
        

    if (!m_RecvThread)
    {
        // Receive in this thread
        m_RecvThread = new Thread(&ServerSession::Receive, this);
    }
}


////////////////////////////////////////////////////////////////////////////////
